﻿using System.Diagnostics;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Web;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using Super.Entities;
using Super.Common.Validate;
using Super.DomainService;
using System.Collections.Generic;
using Super.Common;

namespace System
{
    /// <summary> 全宇宙最底层的康雀乐
    /// </summary>  
    public class CommonController : Controller
    {
        protected const double Expires = 24 * 365; // 默认网站信息 cookies 的时间 - 365days

        private SessionData<string, string> _MessageSessionData;

        public SessionData<string, string> MessageSessionData
        {
            get { return _MessageSessionData ?? (_MessageSessionData = new SessionData<string, string>("MessageSessionData", TimeSpan.FromMinutes(1))); }
        }

        public CommonController()
        {
           Super.Common.DataCache.NowController = this;


            const int defaultSiteAreaID = 286; // 默认常州为分站

            ViewData["Common"] = "这是全站的公牛！";

            //过滤掉来路为Log的日志.
            if (Web.HttpContext.Current.Request.UrlReferrer == null || !Web.HttpContext.Current.Request.UrlReferrer.LocalPath.StartsWith("/_log"))
            {
                //过滤掉_command 和 _log 页面.
                if (!(Web.HttpContext.Current.Request.Path.StartsWith("/_Command") || (Web.HttpContext.Current.Request.Path.StartsWith("/_log"))))
                {
                    Log.FileLog.Write("页面打开", LogType.Hint);
                }
            }
        }

        public LoginUser LoginUser
        {
            get { return SuperService.LoginUser; }
        }

     

        /// <summary> 承志增加_userID,,,避免在Linq查询中大量重复读取cookie....
        /// </summary>
        private int _userId;

        /// <summary> 从当前cookie中获得的UserID  如果未登录,则为int.MinValue
        /// </summary>
        public int UserID
        {
            get
            {
                //if (_userId == 0)
                //{
                //    _userId = LoginUser.UserID;
                //}
                //return _userId;

                return 10;
            }
        }

        /// <summary>  从当前已经登录的cookie中获得的UID
        /// </summary>
        public int UID
        {
            get { return LoginUser.UID; }
        }

        /// <summary> 从当前已经登录的cookie中获得UserName
        /// </summary>
        public string UserName
        {
            get { return LoginUser.UserName; }
        }

        #region 全局获取管理员标示从cookie; 无登录则为int.MinValue;

      
    

        #endregion

        /// <summary> 注册公共页面路由.
        /// </summary>
        /// <param name="routes"></param>
        public static void RegisterCommonRoutes(RouteCollection routes)
        {
            //routes.RouteExistingFiles = false;  //IIS存在的文件是否启用路由

            routes.MapRoute(
                "CommonRoutesVA", //定义一个不能重复的路由名

                "{action}",  //匹配url片段 ，匹配到为自定义名字做变量传入控制器 | 匹配url片段的变量中可以加入*通配，能够匹配所有url片段并以/符号掺入

                new { controller = "Common" },  //提供默认值 ，默认值的 UrlParameter.Optional 为可选匹配值

                new
                {
                    action = "^ValidateCode$|^_Ajax_Json$|^_Command$|^Error$|^_AddFavorite$|^_Log$",  //慢于默认值的匹配，也就是当第一个url片段{action}变量出现时，按此正则匹配 
                    httpMethod = new HttpMethodConstraint("GET", "POST")//,   ////会更早的监控请求方式，满足时才去匹配URL片段 
                    //customConstraint = new UserReferrerConstraint(BangKeService.Domain.Root.ToString()) //这就更有意思了,自定义一个验证规则，我用他判断了来源url  
                },

                new[] { "CommonController" }    //此规则 只从这个控制器类中匹配.匹配不到就回到正常路由
                );

            //routes.MapRoute(
            //    "CommonAjax", // Route name
            //    "_Ajax_Json", // URL with parameters
            //    new { controller = "Common", action = "_Ajax_Json" } // Parameter defaults
            //    );
        }

        #region 消息调用

        /// <summary>
        /// 消息弹出
        /// </summary>
        private void ShowMessage()
        {

            if (MessageSessionData.Count > 0)
            {
                //弹出消息
                this.ViewBag.PageShowMessages = MessageSessionData["msg"];

                MessageSessionData.Remove("msg");//清除消息
            }
        }


        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            if (filterContext.Result is ViewResult)
            {
                ShowMessage();
            }
            base.OnActionExecuted(filterContext);
        }

        protected override void Execute(RequestContext requestContext)
        {
            if (RequestSecure.Current.Request())
                base.Execute(requestContext);
        }


        #endregion

        #region 全局公共控制器================================

        /// <summary> 公共远端验证方法 p=PageKey c=ControlName
        /// </summary>
        /// <param name="p"></param>
        /// <param name="c"></param>
        /// <returns></returns>
        public object ValidateCode(string p, string c)
        {
            var vk = ValidateHelper.UserValidateList[int.Parse(p)];

            if (vk == null)
            {
                return "已超时.请重新刷新页面.(" + ValidateHelper.UserValidateList.Count() + "/" + SessionData<int, List<ValidateRules>>.StaticSessionDataList.Count + ")";
            }

            try
            {

                var validateRoles = vk.LastOrDefault(j => j.ControlName == c);

                if (validateRoles == null)
                {
                    return "规则集合中未发现此控件.";
                }

                //包含代码逻辑的规则
                var fs = validateRoles.ValidateElementList.LastOrDefault(j => j.Type == "remote");

                if (fs == null)
                {
                    return "未发现控件的远端规则.";
                }

                /*
                if (fs.ValidateMethodByMultiParameter != null)
                {
                    return fs.ValidateMethodByMultiParameter.Invoke(Web.HttpContext.Current.Request) ? "true" : "false";
                }
                 */

                var value = Web.HttpContext.Current.Request[c];

                return fs.ValidateMethodByRemote.Invoke(value);
            }
            catch (Exception ex)
            {
#if DEBUG
                return "<b>验证逻辑错误!<b> " + ex.Message;
#else
                return "<b>验证逻辑错误!<b> <b style=\"display:none\">" + ex.Message + "</b>";
#endif

            }
        }

        /// <summary> 公共AJAX透传
        /// </summary>
        /// <param name="code"></param>
        /// <param name="type"></param>
        /// <returns>输出json头内容</returns>
        /// <remarks>名字为什么这么怪？因为这是系统全局的，怕重复</remarks>
        // ReSharper disable InconsistentNaming
        public ContentResult _Ajax_Json(string code, string type = "JSON")
        // ReSharper restore InconsistentNaming
        {
            if (!string.IsNullOrEmpty(code))
            {
                if (type.ToUpper().Equals("JSON"))
                {
                    //Response.ContentType = "application/json";
                    code = HttpUtility.UrlDecode(code);
                    return Content(code);

                    //TODO:还需要加强
                }
            }
            return Content("");
        }


        /*   没了.
        /// <summary> 公共错误页面.
        /// </summary>
        /// <returns></returns>
        [LinkFilter]
        public ActionResult Error()
        {
            return ErrorPage("500.1", "抱歉.您的页面已超时.");
        }
        */

        #region 私有方法

        /// <summary> 发送更新缓存信息
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <param name="ids"></param>
        /// <returns></returns>
        private string SendUpdateCacheMessage(string entityType, string ids)
        {
            try
            {
                //DataCache.EntityCache.CacheEntityRules[typeof(BK_BaseEntity).Assembly.GetType("BK.Entities." + entityType)].UpdateCacheList(ids.Split(',').Select(int.Parse).ToArray());
                return "ok";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }

        }

        #endregion

        /// <summary> 公共控制器命令.
        /// </summary>
        /// <returns></returns>
        public object _Command(string cmd)
        {
            switch (cmd)
            {
                case "ClearLog":
                    return Log.FileLog.Clear();
              
                case "ValidatePant":
                    return ValidateHelper.Pant();
                case "Time":
                    return DateTime.Now;
                //case "Login":  //用户登入, 成功返回ok, 失败返回失败信息.
                //    return UserService.Login() ?? "ok";
                //case "Register":
                //    return UserService.Register(SiteAreaID) ?? "ok";
              
            }

            return "未知的命令 " + cmd;
        }

        /// <summary> 查看系统日志
        /// </summary>
        /// <returns></returns>
        public ActionResult _Log(int count = 200, string userName = null, LogType? logType = null, string info = null, string ip = null, DateTime? beginTime = null, DateTime? endTime = null, string url = null)
        {
            var lf = Log.FileLog.Read(count, userName, info, logType, ip, beginTime, endTime, url);

            var sb = new StringBuilder();
            sb.AppendFormat("<p>{0} &nbsp写入错误/新写入日志:{1}/{2}.</p>", DateTime.Now, Log.FileLog.NewLogWriteError, Log.FileLog.NewLogCount);
            sb.AppendFormat("<p>ApplicationStartTime:{3};Validate Key/MyKey/Session:{0}/{6}/{1};ValidateRules:{2};BkMessage/Session:{4}/{5}</p>"
                    , SessionData<int, List<ValidateRules>>.StaticSessionDataList.Sum(j => j.Value.Value.Count)
                    , SessionData<int, List<ValidateRules>>.StaticSessionDataList.Count
                    , ValidateHelper.AllValidateRulesList.Count
                    , ApplicationService.StartTime
                    , SessionData<string, string>.StaticSessionDataList.Sum(j => j.Value.Value.Count)
                    , SessionData<string, string>.StaticSessionDataList.Count
                    , ValidateHelper.UserValidateList.Count
                );

            sb.Append("<table border=\"1\" rules=\"all\"><tr><th width=150>日期</th><th width=110>类别</th><th width=170>IP</th><th width=300>URL</th><th>内容</th><th width=80>用户</th></tr>");
            foreach (var logInfo in lf)
            {
                sb.Append("<tr><td>&nbsp" + logInfo.DateTime.ToString("MM/dd HH:mm:ss") + "&nbsp</td><td>&nbsp&nbsp" + logInfo.Type +
                    "&nbsp&nbsp</td><td>&nbsp" + (logInfo.Ip != "127.0.0.1" ? "<a href=\"/_log?ip=" + logInfo.Ip + "\">" + logInfo.Ip + "</a>" + "<a href=\"http://www.baidu.com/s?wd=" + logInfo.Ip + "\">查</a>" : logInfo.Ip)
                    + "</a>&nbsp&nbsp</td><td><a href=\"" + logInfo.Url + "\">" + (logInfo.Url.Length < 50 ? logInfo.Url : logInfo.Url.Remove(45) + "...")
                    + "</a>" + (logInfo.RefUrl == "" ? "" : "<br/><a href=\"" + logInfo.RefUrl + "\">" + (logInfo.RefUrl.Length < 50 ? logInfo.RefUrl : logInfo.RefUrl.Remove(45) + "...")
                    + "</a>") + "<td>&nbsp&nbsp<a " + (logInfo.Detail != "" ? " href=\"_Command?cmd=LogDetail&line=" + logInfo.Line + "\"" : "") + ">" + logInfo.Info + "</a>&nbsp&nbsp</td><td>" + logInfo.UserName + "</td></tr>");
            }

            sb.Append("</table><a href=\"_Command?cmd=ClearLog\">ClearLog</a>");

            return Content(sb.ToString());
        }

        /// <summary> 全局错误页 ,这是一个Content类型的爱可信
        /// </summary>
        /// <param name="errorCode"></param>
        /// <param name="errorDescription"></param>
        /// <returns></returns>
        [ValidateInput(false)]
        public ContentResult ErrorPage(string errorCode = "404", string errorDescription = "")
        {
            return Content(SuperService.WebErrorPage(errorCode, errorDescription));
        }

        public HttpNotFoundResult NotFound(string ErrDescription = null)
        {
            return HttpNotFound(ErrDescription);
        }


        #endregion
    }

    /// <summary> 这只是一个自定义路由匹配规则的类  
    /// </summary>
    public class UserReferrerConstraint : IRouteConstraint
    {
        private string requiredUserReferrer;
        public UserReferrerConstraint(string agentParam)
        {
            requiredUserReferrer = agentParam;
        }
        public bool Match(HttpContextBase httpContext, Route route, string parameterName,
                  RouteValueDictionary values, RouteDirection routeDirection)
        {
            return httpContext.Request.UrlReferrer != null &&
            httpContext.Request.UrlReferrer.Host.Contains(requiredUserReferrer); //来源地址包含
        }
    }

}
